﻿using InfluxData.Net.Common.Enums;
using InfluxData.Net.Common.Infrastructure;
using InfluxData.Net.InfluxDb;
using InfluxData.Net.InfluxDb.Models;
using InfluxData.Net.InfluxDb.Models.Responses;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace Infrastructure
{
    /// <summary>
    /// InfluxDB帮助类
    /// </summary>
    public class InfluxDBHelper
    {
        #region 构造函数

        /// <summary>
        /// 实例化
        /// </summary>
        /// <exception cref="Exception"></exception>
        public InfluxDBHelper()
        {
            ProjectName = Config.ReadSetting("InfluxDB:Project");
            InfluxDBUrl = Config.ReadSetting("InfluxDB:Url");
            Account = Config.ReadSetting("InfluxDB:Account");
            Password = Config.ReadSetting("InfluxDB:Password");

            if (string.IsNullOrEmpty(ProjectName) || string.IsNullOrEmpty(InfluxDBUrl))
            {
                throw new Exception("获取配置文件InfluxDB配置信息错误");
            }
        }

        /// <summary>
        /// 实例化
        /// </summary>
        /// <param name="name"></param>
        /// <param name="url"></param>     
        /// <param name="account"></param>
        /// <param name="password"></param>
        /// <exception cref="Exception"></exception>
        public InfluxDBHelper(string name, string url, string account, string password)
        {
            ProjectName = name;
            InfluxDBUrl = url;
            Account = account;
            Password = password;

            if (string.IsNullOrEmpty(ProjectName) || string.IsNullOrEmpty(InfluxDBUrl))
            {
                throw new Exception("实例化InfluxDB错误,未传递地址/库名参数信息");
            }
        }

        /// <summary>
        /// 库名
        /// </summary>
        static string ProjectName;

        /// <summary>
        /// 地址
        /// </summary>
        static string InfluxDBUrl;

        /// <summary>
        /// 用户名
        /// </summary>
        static string Account;

        /// <summary>
        /// 密码
        /// </summary>
        static string Password;

        /// <summary>
        /// 客户端
        /// </summary>
        private static InfluxDbClient clientDb = null;

        private static InfluxDbClient ClientDb
        {
            get
            {
                //IL_0021: Unknown result type (might be due to invalid IL or missing references)
                //IL_002b: Expected O, but got Unknown
                if (clientDb == null)
                {
                    clientDb = new InfluxDbClient(InfluxDBUrl, Account, Password, (InfluxDbVersion)0, (QueryLocation)1, (HttpClient)null, false);
                }
                return clientDb;
            }
        }

        #endregion

        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="query">sql语句</param>
        /// <returns></returns>
        [DebuggerStepThrough]
        public static async Task<IEnumerable<Serie>> QueryAsync(string query)
        {
            //从指定库中查询数据
            var response = await ClientDb.Client.QueryAsync(query, ProjectName);

            return response;
            ////得到Serie集合对象（返回执行多个查询的结果）
            //var series = response.ToList();
            ////取出第一条命令的查询结果，是一个集合
            //var list = series[0].Values;
            ////从集合中取出第一条数据
            //var info_model = list.FirstOrDefault();
        }

        /// <summary>
        /// 单个添加数据
        /// </summary>
        /// <param name="tabName">表名</param>
        /// <param name="jsonData">数据对象</param>
        /// <param name="source">数据源</param>
        public async Task<IInfluxDataApiResponse> AddDataAsync(string tabName, string jsonData, string source = "default")
        {
            if (string.IsNullOrEmpty(jsonData))
            {
                throw new Exception("InfluxDB存储数据为空");
            }
            var data = ConvertJsonExtension.DeserializeObject<Dictionary<string, object>>(jsonData);

            var fields = new Dictionary<string, object>() { { "db_source", source } };

            //基于InfluxData.Net.InfluxDb.Models.Point实体准备数据
            var point_model = new Point()
            {
                Name = tabName,//表名
                Tags = data,
                Fields = fields,
                Timestamp = DateTime.UtcNow
            };

            //从指定库中写入数据，支持传入多个对象的集合
            return await ClientDb.Client.WriteAsync(point_model, ProjectName);
        }

        /// <summary>
        /// 批量添加数据
        /// </summary>                                   
        /// <param name="tabName">表名</param>
        /// <param name="jsonData">数据对象</param>
        /// <param name="source">数据源</param>
        public async Task<IInfluxDataApiResponse> AddDataAsync(string tabName, List<string> jsonData, string source = "default")
        {
            //基于InfluxData.Net.InfluxDb.Models.Point实体准备数据
            if (jsonData.Count == 0)
            {
                throw new Exception("InfluxDB存储数据为空");
            }

            var fields = new Dictionary<string, object>() { { "db_source", source } };

            var list = new List<Point>();
            foreach (var item in jsonData)
            {
                var data = ConvertJsonExtension.DeserializeObject<Dictionary<string, object>>(item);
                list.Add(new Point()
                {
                    Name = tabName,//表名
                    Tags = data,
                    Fields = fields,
                    Timestamp = DateTime.UtcNow
                });
            }

            //从指定库中写入数据，支持传入多个对象的集合
            return await ClientDb.Client.WriteAsync(list, ProjectName);
        }
    }
}
